package com.hobbit.net
{
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.events.TimerEvent;
	import flash.net.Socket;
	import flash.system.Security;
	import flash.utils.ByteArray;
	import flash.utils.Endian;
	import flash.utils.Timer;
	
	
	/**
	 * socket 
	 * @author 晓晔
	 * 
	 */
	public class MSocket extends Socket
	{
		public function MSocket()
		{
			super();
			this.endian = Endian.LITTLE_ENDIAN;
			initListener();
		}
		
		private function initListener():void
		{
			this.addEventListener(Event.CONNECT,onConnect);
			this.addEventListener(ProgressEvent.SOCKET_DATA,onSocketData);
			this.addEventListener(Event.CLOSE,onClose);
			this.addEventListener(SecurityErrorEvent.SECURITY_ERROR,onSecurity);
			this.addEventListener(IOErrorEvent.IO_ERROR,ioErrorHandler);
		}
		
		
		/**
		 * 当前socket是否已连接 
		 */	
		private var _connected:Boolean = false;
		
		private function onConnect(e:Event):void
		{
			_connected = true;
			trace("已经连接");
		}
		private function onClose(e:Event):void
		{
			if(retrySocket() == false)
			{
				trace("socket_close");
				_connected = false;
//				var socketEvent:NetEvent = new NetEvent(NetEvent.NET_FSOCKET_CLOSE);
//				dispatchEvent(socketEvent);
			}
		}
		
		private function onSecurity(e:SecurityErrorEvent):void
		{
			retrySocket();
		}
		
		private function ioErrorHandler(e:IOErrorEvent):void
		{
			retrySocket();
		}
		
		/**
		 * 重新连接 
		 * @return 
		 * 
		 */		
		private function retrySocket():Boolean
		{
			if(_portIndex >= _portList.length - 1)
			{
				return false;
			}else{
				_portIndex += 1;
				_port = _portList[_portIndex];
				connect(_host,_port);
				return true;
			}
			return false;
		}
		
		private var _readHead:Boolean = false;
		private var _cLength:int = 0;
		private var _cCmd:int = 0;
		private var _cRes:int = 0;
		private var _cData:ByteArray;
		/**
		 * 数据处理 
		 * @param e
		 * 
		 */		
		private function onSocketData(e:ProgressEvent):void
		{
		
			var uncomp:Boolean;
			var bytes:ByteArray;
			var tmp_len:uint;
			while (this.bytesAvailable > LEN) {
				this.endian = Endian.LITTLE_ENDIAN;
				uncomp = false;
//				trace("socket.bytesAvailable"+ this.bytesAvailable + " available");
				if(_length==-1){
					tmp_len = this.readUnsignedInt();
					_length = tmp_len - LEN;
//					trace("socket tmp_len and _length" + tmp_len + ":" + _length);
					if (_length & compress) 
					{
//						trace("compressed before " +  _length);
						uncomp = true;
						_length = compress ^ _length;
//						trace("compressed after " +  _length);
					}
				}
//				trace("socket length " + _length + ":" + this.bytesAvailable + " available:");
				if (_length <= this.bytesAvailable) {
					//                    trace("socket length guo available:");
					bytes = new ByteArray();
					bytes.endian = "littleEndian";
					this.readBytes(bytes, 0, _length);
					if(uncomp) {
						bytes.uncompress();
					}
//					dispatchEvent(new NetEvent(NetEvent.NET_COMPLETE,bytes));
					
					_length=-1;
				} else {
//					trace('LEN >  socket.bytesAvailable')
					break;
				}
			}
			
		}
		
		/**
		 * socket 连接地址 
		 */		
		private var _host:String = "";
		/**
		 * socket 连接端口 
		 */		
		private var _port:int = 0;
		
		/**
		 * socket连接端口列表 
		 */		
		private var _portList:Array = [];
		/**
		 * 端口索引 
		 */		
		private var _portIndex:int = 0;
		
		/**
		 * 连接socket
		 * @param host socket地址
		 * @param port socket端口，多个端口用 | 分隔
		 * @param policy 不同域 域名
		 */
		public function connectMulti(host:String,port:String,policy:String = null):void
		{
			if (policy) Security.loadPolicyFile(policy);
			
			_host = host;
			_portList = port.split("|");
			_port = _portList[_portIndex];
			connectServer(host,_port);
		}
		
		private var timer:Timer;
		private function connectServer(host:String,port:int):void
		{
			super.connect(host,port);
			
			//心跳机----
			if(timer != null) timer.removeEventListener(TimerEvent.TIMER,onTimer);
			timer = new Timer(6000,1);
			timer.addEventListener(TimerEvent.TIMER,onTimer);
			timer.start();
		}
		private function onTimer(event:TimerEvent):void
		{
			this.retrySocket();
		}
		
		
		/**
		 * 发送数据 
		 * @param data
		 * 
		 */		
		public function send(data:ByteArray):void
		{
			
			/*if (_connected)
			{
				var byte:ByteArray = new ByteArray();;              
				var length:int = data.length + LEN;
				this.endian = Endian.BIG_ENDIAN;
				
				byte.writeUnsignedInt(length);
				byte.writeBytes(data);         
				var md5:String = SocketEncryption.getBAHash(byte);
				byte.position = 10;
				byte.writeBytes( DataParser.getCharByte( md5, 32 ), 0, 32 );
				this.writeBytes( byte );
				
				this.flush();
			}
			else
			{
				retrySocket();
			}*/
			
		}
		
		static private const LEN:int = 4;
		static private const COMPRESS_LENGTH:int = 1024;
		static private const compress:uint = 1 << 31;
		private var _length:int=-1;//合包用
		
	}
}